package cn.cosmosx.service.sys;

import cn.cosmosx.base.constant.GlobalConstant;
import cn.cosmosx.base.constant.ResultCode;
import cn.cosmosx.base.encrypt.aes.AESUtil;
import cn.cosmosx.base.helper.CurrentThreadContextHelper;
import cn.cosmosx.base.helper.SessionHelper;
import cn.cosmosx.base.security.entity.SecurityUserVo;
import cn.cosmosx.base.security.service.CacheProviderService;
import cn.cosmosx.base.util.CookieUtils;
import cn.cosmosx.base.util.ResponseUtils;
import lombok.SneakyThrows;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.authentication.AuthenticationProvider;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.core.Authentication;
import org.springframework.stereotype.Service;

import javax.servlet.http.Cookie;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;

/**
 * 认证service
 */
@Service
public class AuthenticationService {
    @Autowired
    private AuthenticationProvider authenticationProvider;
    @Autowired
    private CacheProviderService cacheProviderService;

    /**
     * 用户登录
     *
     * @param username - 用户名
     * @param password - 密码
     */
    @SneakyThrows
    public void login(String username, String password) {
        try {
            // 调用SpringSecurity自定义登录认证器执行登录。UsernamePasswordAuthenticationToken下的super.setAuthenticated(false);
            UsernamePasswordAuthenticationToken token = new UsernamePasswordAuthenticationToken(username, password);
            Authentication authentication = authenticationProvider.authenticate(token);
            // 拿到设置的SecurityUserVo
            SecurityUserVo principal = (SecurityUserVo) authentication.getPrincipal();
            // 登录成功设置信息
            successfullyAuthenticate(principal, CurrentThreadContextHelper.getResponse());
        } catch (Exception e) {
            ResponseUtils.wrapResponse(CurrentThreadContextHelper.getResponse(), ResultCode.U90001);
        }
    }

    /**
     * 登录成功
     *
     * @param session  - 用户session
     * @param response - 响应response
     */
    protected void successfullyAuthenticate(SecurityUserVo session, HttpServletResponse response) throws IOException {
        String token = cacheProviderService.createToken(session);
        // 踢掉之前登录的人（清除Redis登录缓存）
        cacheProviderService.clearCache(session.getUserId());
        // 缓存 access-token
        cacheProviderService.saveToken(session, token);
        // 登陆成功后, 给响应头置入 access-token
        String encryptToken = AESUtil.encrypt(token);// 加密token
        response.setHeader(GlobalConstant.TOKEN, encryptToken);
        // 测试用的时候为了配合swagger，使用cookie
        CookieUtils.saveToken(encryptToken, response);
        //存 user 到本地线程中
        SessionHelper.put(session);
        ResponseUtils.successfulResponse(response);
    }


    /**
     * 退出登录
     */
    public void logout() {
        // 清除已登录用户的token信息
        cacheProviderService.clearCache(SessionHelper.getUserId());
        //1 服务端数据清理
        SessionHelper.clear();
        //2 客户端数据清理
        //清除用户端cookie认证信息
        Cookie cookie = new Cookie(GlobalConstant.TOKEN, "");
        cookie.setPath("/");
        cookie.setMaxAge(0);
        CurrentThreadContextHelper.getResponse().addCookie(cookie);
        //重置客户端header中的认证信息
        CurrentThreadContextHelper.getResponse().setHeader(GlobalConstant.TOKEN, "");
    }
}
